#include <stdio.h>
#include <math.h>
#include <pthread.h>
#define precision 1000
#define steps 200

int n_threads = precision/steps;
int x = 0;
pthread_t threads[precision/steps];
double results[precision/steps];


void log_x(int n) {
  int i;
  double a, b;
  results[n] = 0;
  a = (x - 1) / (double) x;
  for (i = n + 1; i <= precision; i = i + n_threads) {
    b = 1.0 / i;
    results[n] += pow(a, i) * b;
  }
}

void sub(int i, double *total) {
    pthread_join(threads[i], NULL);
    *total += results[i];
}

int main() {
  int exausted = 0;
  double total = 0.0;
  int i, j = 0;

  printf("Type in a value for calculating it's log:");
  scanf("%d", &x);
  printf("Calculating log(%d) with precision %d "
         "using %d threads (step=%d).\n", x,
         precision, n_threads, steps);

  for (i = 0; i < n_threads; i++) {
    while (pthread_create(&threads[i], NULL, (void *) log_x, (void *) i)) {
      // Wait for some threads to finish to make room for more.
      if (j + 1 < i) {
        if (!exausted) {
          printf("Thread limit exausted at %d, started joining threads "
                 "to make room.\n", i);
          exausted = 1;
        }
        sub(j, &total);
        j++;
      }
    }
  }

  for (i = j; i < n_threads; i++) {
    sub(i, &total);
  }

  printf("log(%d) = %.17f\n", x, total);
}
